package logger

import (
	"errors"
	"io"
	"io/ioutil"
	"log"
	"os"
)

//默认是否彩色打印
var isColor = true

type logType int

//日志等级
const (
	LevelTrace logType = iota //基本输出
	LevelInfo                 //系统输出
	LevelDebug                //系统调试
	LevelWarn                 //系统警告,提示有可预测的错误
	LevelError                //程序错误,不影响继续使用
	LevelPanic                //程序异常，递归调用本层及上层defer后，中断程序进程，类似java的异常处理
	LevelFatal                //(致命的错误)程序直接结束，打印错误信息后直接调用os.Exit(1)结束程序，不会调用各层defer
)

type colorType uint8

//日志打印颜色
const (
	colorBlack    colorType = iota + 30 //Golang中实现枚举就是用这种方式
	colorRed                            //红色
	colorGreen                          //绿色
	colorYellow                         //黄色
	colorBlue                           //蓝色
	colorPurple                         //紫色
	colorDarkBlue                       //碧蓝(深蓝)
)

//window系统下日志打印颜色
const (
	WinColorBlue     colorType = iota + 9 //深蓝
	WinColorGreen                         //绿色
	WinColorDarkBlue                      //碧蓝
	WinColorRed                           //红色
	WinColorPurple                        //紫色
	WinColorYellow                        //黄色
)

//日志头部标志
const (
	lTrace  = "[Trace]"
	lInfo   = "[Info]"
	lDebug  = "[Debug]"
	lWarn   = "[Warn]"
	lError  = "[Error]"
	lPanic  = "[Panic]"
	lFatal  = "[Fatal]"
)

/*
初始化日志记录器:
0 - 2层信息输出到os.stdout
3 - 6层信息输出到os.stderr
*/
var logger = []*log.Logger{
	LevelTrace: log.New(os.Stdout,"",0),
	LevelInfo:  log.New(os.Stdout,"",0),
	LevelDebug: log.New(os.Stdout,"",0),
	LevelWarn:  log.New(os.Stderr,"",0),
	LevelError: log.New(os.Stderr,"",0),
	LevelPanic: log.New(os.Stderr,"",0),
	LevelFatal: log.New(os.Stderr,"",0),
}

//是否彩色打印
func IsColor(yes bool){
	isColor = yes
}

//LogHide 隐藏单个日志级别的输出信息
//传入需要隐藏的日志级别，日志级别不能超过LevelPanic
func LogHide(t logType)error {
	if t > LevelPanic {
		return errors.New(" 参数 t 不能超过 LevelPanic!")
	}
	logger[t].SetOutput(ioutil.Discard) //设置日志记录器的输出目标。
	return nil
}

//LogHideMany 隐藏多个日志级别输出信息
//传入需要隐藏的日志级别，最高设置到LevelPanic 即是低于panic等级的日志都不显示
func LogHideMany(t logType) error {
	if t > LevelPanic {
		return errors.New(" 参数 t 不能超过 LevelPanic!")
	}
	for i := int(t); i >= 0; i-- {
		if i <= 3 {
			logger[logType(i)].SetOutput(os.Stdout)
		} else {
			logger[logType(i)].SetOutput(os.Stderr)
		}
	}
	for i := 0; i < int(t); i++ {
		logger[logType(i)].SetOutput(ioutil.Discard)
	}
	return nil
}

//SetOutput 设置单个日志级别输出到目标位置
//传入文件的句柄（或者实现了io.Writer接口的对象）与日志级别，则该日志级别的日志将会输出到指定的文件或位置
func SetOutput(w io.Writer, t logType) {
	logger[t].SetOutput(w)
}

//SetOutputAll 设置全部日志级别输出到目标位置
//传入文件的句柄（或者实现了io.Writer接口的对象）与日志级别，则全部日志级别的日志将会输出到指定的文件或位置
func SetOutputAll(w io.Writer) {
	for i := range logger {
		logger[i].SetOutput(w)
	}
}

//SetOutputAbove设置指定日志级别及以上的输出到目标位置
//传入文件的句柄（或者实现了io.Writer接口的对象）与日志级别，则该日志级别以上的日志（包括此日志级别）将会输出到指定的文件或位置
func SetOutputAbove(w io.Writer, t logType) {
	for i := int(t); i < 7; i++ {
		logger[logType(i)].SetOutput(w)
	}
}

//SetOutputBelow设置指定日志级别及以下的输出到目标位置
//传入文件的句柄（或者实现了io.Writer接口的对象）与日志级别，则该日志级别以下的日志（包括此日志级别）将会输出到指定的文件或位置
func SetOutputBelow(w io.Writer, t logType) {
	for i := 0; i <= int(t); i++ {
		logger[logType(i)].SetOutput(w)
	}
}

type Logger struct {
	logger []*log.Logger
	isColor bool
}

//生成一个新的日志对象
func NewLogger() Logger {
	loggers := []*log.Logger{
		LevelTrace: log.New(os.Stdout, "", 0),
		LevelInfo:  log.New(os.Stdout, "", 0),
		LevelDebug: log.New(os.Stdout, "", 0),
		LevelWarn:  log.New(os.Stderr, "", 0),
		LevelError: log.New(os.Stderr, "", 0),
		LevelPanic: log.New(os.Stderr, "", 0),
		LevelFatal: log.New(os.Stderr, "", 0),
	}
	return Logger{loggers, true}
}

//LogHide 隐藏单个日志级别的输出信息
//传入需要隐藏的日志级别，日志级别不能超过LevelPanic
func (l Logger) LogHide(t logType) error {
	if t > LevelPanic {
		return errors.New(" 参数 t 不能超过 LevelPanic!")
	}
	l.logger[t].SetOutput(ioutil.Discard)
	return nil
}

//LogHideMany 隐藏多个日志级别输出信息
//传入需要隐藏的日志级别，最高设置到LevelPanic 即是低于panic等级的日志都不显示
func (l Logger) LogHideMany(t logType) error {
	if t > LevelPanic {
		return errors.New(" 参数 t 不能超过 LevelPanic!")
	}
	for i := int(t); i >= 0; i-- {
		if i <= 3 {
			l.logger[logType(i)].SetOutput(os.Stdout)
		} else {
			l.logger[logType(i)].SetOutput(os.Stderr)
		}
	}
	for i := 0; i < int(t); i++ {
		l.logger[logType(i)].SetOutput(ioutil.Discard)
	}
	return nil
}

//是否彩色打印
func (l *Logger) IsColor(color bool) {
	l.isColor = color
}

//设置单个日志级别输出到目标位置
func (l Logger) SetOutput(w io.Writer, t logType) {
	l.logger[t].SetOutput(w)
}

//设置全部日志级别输出到目的地
func (l Logger) SetOutputAll(w io.Writer) {
	for i := range l.logger {
		l.logger[i].SetOutput(w)
	}
}

//设置指定日志级别及以上的输出到目标位置
func (l Logger) SetOutputAbove(w io.Writer, t logType) {
	for i := int(t); i < 7; i++ {
		l.logger[logType(i)].SetOutput(w)
	}
}

//设置指定日志级别及以下的输出到目标位置
func (l Logger) SetOutputBelow(w io.Writer, t logType) {
	for i := 0; i <= int(t); i++ {
		l.logger[logType(i)].SetOutput(w)
	}
}





